package git.soulbgm.controller;

import git.soulbgm.pojo.AliveInfo;
import git.soulbgm.pojo.Server;
import git.soulbgm.pojo.TimeSyncInfo;
import git.soulbgm.utils.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * @author SoulBGM
 * @date 2020/6/28 15:24
 */
@RestController
public class MonitorController {

    private static final LogUtil LOG = new LogUtil(MonitorController.class);

    /**
     * 心跳接口
     *
     * @return up
     */
    @GetMapping("heartbeat")
    public String heartbeat() {
        return "up";
    }

    /**
     * 获取硬件状态信息
     *
     * @return 硬件状态信息
     */
    @GetMapping("info")
    public Server runInfo() {
        return MonitorUtil.getLatestServer();
    }

    /**
     * 获取时间同步的信息
     *
     * @return {@link TimeSyncInfo}
     */
    @GetMapping("ntpdate")
    public TimeSyncInfo ntpdate() {
        return MonitorUtil.getLatestNtpdateInfo();
    }

    /**
     * 执行命令
     *
     * @param request HttpServletRequest对象
     * @param command 命令
     * @return 命令运行结果内容
     */
    @PostMapping("exec")
    public String exec(HttpServletRequest request, String command) {
        String result = CmdUtil.execStr(command);
        LOG.info("IP:{} 执行了 {} 命令, 得到的结果如下\n{}", RequestUtil.getIpAddress(request), command, result);
        return result;
    }

    /**
     * 是否存活
     *
     * @param processNames 软件进程名称和端口号 多个以,隔开
     * @return 软件进程存活状态
     */
    @GetMapping("isAlive")
    public List<AliveInfo> isAlive(String processNames) {
        String[] processNameArray = processNames.split(",");
        List<AliveInfo> list = new ArrayList<>(processNameArray.length);
        for (String s : processNameArray) {
            String[] processNameAndPortSplit = s.split(":");
            AliveInfo info = CmdUtil.isAlive(processNameAndPortSplit[0]);
            info.setName(s);
            if (processNameAndPortSplit.length > 1) {
                if (info.getStatus() && !CmdUtil.isAlive(Integer.parseInt(processNameAndPortSplit[1]))) {
                    info.setStatus(false);
                }
            }
            list.add(info);
        }
        return list;
    }

    @GetMapping("getFile")
    public String getFile(HttpServletResponse response, String path) {
        Path filePath = Paths.get(path);
        boolean flag = Files.exists(filePath);
        if (!flag) {
            return "不存在 " + path + " 文件或目录";
        }
        boolean isDirectory = Files.isDirectory(filePath);
        String fileName = filePath.getFileName().toString();
        response.setHeader("Content-Disposition", String.format("attachment; filename=%s", fileName + (isDirectory ? ".zip" : "")));
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            if (isDirectory) {
                response.setContentType("application/zip");
                ZipUtil.zip(outputStream, filePath.toFile());
            } else {
                response.setContentType("application/octet-stream");
                Files.copy(filePath, outputStream);
            }
        } catch (Exception e) {
            return "输出出现异常(" + e.getMessage() + ")";
        }
        return "success";
    }

    private static final String LEVEL_DEBUG = "debug";
    private static final String LEVEL_INFO = "info";
    private static final String LEVEL_WARN = "warn";
    private static final String LEVEL_ERROR = "error";

    /**
     * 获取日志接口
     *
     * @param response 响应
     * @param zipName  邮政的名字
     * @param logPath  日志路径
     * @return {@link String}
     */
    @GetMapping("getLog")
    public String getLog(HttpServletResponse response, String zipName, String logPath) {
        if (logPath == null || logPath.isEmpty()) {
            return "logPath参数不能为空";
        }
        try {
            String level = logPath.substring(logPath.lastIndexOf("/") + 1);
            level = level.toLowerCase();
            String parent = logPath.substring(0, logPath.lastIndexOf("/"));
            File[] fileArray = new File[1];
            if (LEVEL_DEBUG.equalsIgnoreCase(level) ||
                    LEVEL_INFO.equalsIgnoreCase(level) ||
                    LEVEL_WARN.equalsIgnoreCase(level) ||
                    LEVEL_ERROR.equalsIgnoreCase(level)) {
                File parentFile = new File(parent);
                if (!parentFile.exists()) {
                    return "no";
                }
                if (zipName == null || zipName.isEmpty()) {
                    zipName = parentFile.getName() + ".zip";
                }
                File[] files = parentFile.listFiles();
                if (files == null || files.length == 0) {
                    return "no";
                }
                List<File> fileList = new ArrayList<>();
                for (File file : files) {
                    if (file.getName().startsWith(level)) {
                        fileList.add(file);
                    }
                }
                if (fileList.isEmpty()) {
                    return "no";
                }
                fileArray = new File[fileList.size()];
                for (int i = 0; i < fileArray.length; i++) {
                    fileArray[i] = fileList.get(i);
                }
            } else {
                File logFile = new File(logPath);
                if (!logFile.exists()) {
                    return "no";
                }
                if (zipName == null || zipName.isEmpty()) {
                    zipName = logFile.getName() + ".zip";
                }
                fileArray[0] = logFile;
            }
            ResponseUtil.setResponse(response, zipName);
            OutputStream out = response.getOutputStream();
            ZipUtil.zip(out, fileArray);
            return "success";
        } catch (Exception e) {
            //e.printStackTrace();
            return "error";
        }
    }

}
